/*
 * SimpleCipherForm.java
 * 
 * Copyright (C) 2007 Francisco J. Hernández
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package simpleciphertext;

import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;

/**
 *
 * @author  Lhrod
 */
public class SimpleCipherForm extends javax.swing.JFrame {

    public static final java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("simpleciphertext/SimpleCipherText");
    private static final int VERSION = 0;
    private static final int REVISION = 53;
    public static final String SVERSION = VERSION + "." + REVISION;
    public static final String TITLE = "SimpleCipherText";
    private static final String FORMAT_TXT = ".txt";
    private static final String FORMAT_SC = ".sc";
    private static final String[] formats = new String[]{FORMAT_TXT, FORMAT_SC};
    private static File file;
    private static String password = null;

    /** Creates new form SimpleCipherForm */
    public SimpleCipherForm() {
        initComponents();
        init();
    }

    /**
     * Inic all variables
     */
    private void init() {
        file = null;
        textArea.setText("");
        setTitle(TITLE + " " + SVERSION);
        saveMenuItem.setEnabled(false);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
  private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    jScrollPane1 = new javax.swing.JScrollPane();
    textArea = new simpleciphertext.SimpleEditorTextArea();
    jMenuBar1 = new javax.swing.JMenuBar();
    optMenu = new javax.swing.JMenu();
    setPasswordMenuItem = new javax.swing.JMenuItem();
    jSeparator3 = new javax.swing.JSeparator();
    newMenuItem = new javax.swing.JMenuItem();
    jSeparator4 = new javax.swing.JSeparator();
    openMenuItem = new javax.swing.JMenuItem();
    saveMenuItem = new javax.swing.JMenuItem();
    saveasMenuItem = new javax.swing.JMenuItem();
    jSeparator1 = new javax.swing.JSeparator();
    aboutOfMenuItem = new javax.swing.JMenuItem();
    jSeparator5 = new javax.swing.JSeparator();
    exitMenuItem = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setIconImage(new javax.swing.ImageIcon(getClass().getResource(bundle.getString("icon"))).getImage());

    jPanel1.setLayout(new java.awt.BorderLayout());

    textArea.setColumns(20);
    textArea.setRows(5);
    jScrollPane1.setViewportView(textArea);

    jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER);

    getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("simpleciphertext/SimpleCipherText"); // NOI18N
    optMenu.setText(bundle.getString("optMenu.text")); // NOI18N

    setPasswordMenuItem.setText(bundle.getString("setPasswordMenuItem.text")); // NOI18N
    setPasswordMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        setPasswordMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(setPasswordMenuItem);
    optMenu.add(jSeparator3);

    newMenuItem.setText(bundle.getString("newMenuItem.text")); // NOI18N
    newMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        newMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(newMenuItem);
    optMenu.add(jSeparator4);

    openMenuItem.setText(bundle.getString("openMenuItem.text")); // NOI18N
    openMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        openMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(openMenuItem);

    saveMenuItem.setText(bundle.getString("saveMenuItem.text")); // NOI18N
    saveMenuItem.setEnabled(false);
    saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        saveMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(saveMenuItem);

    saveasMenuItem.setText(bundle.getString("saveasMenuItem.text")); // NOI18N
    saveasMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        saveasMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(saveasMenuItem);
    optMenu.add(jSeparator1);

    aboutOfMenuItem.setText(bundle.getString("aboutOfMenuItem.text")); // NOI18N
    aboutOfMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        aboutOfMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(aboutOfMenuItem);
    optMenu.add(jSeparator5);

    exitMenuItem.setText(bundle.getString("exitMenuItem.text")); // NOI18N
    exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        exitMenuItemActionPerformed(evt);
      }
    });
    optMenu.add(exitMenuItem);

    jMenuBar1.add(optMenu);

    setJMenuBar(jMenuBar1);

    pack();
  }// </editor-fold>//GEN-END:initComponents

private void aboutOfMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutOfMenuItemActionPerformed
    // TODO add your handling code here:
    new AboutDialog(this, true).setVisible(true);
}//GEN-LAST:event_aboutOfMenuItemActionPerformed

private void newMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newMenuItemActionPerformed
    // TODO add your handling code here:
    init();
}//GEN-LAST:event_newMenuItemActionPerformed

private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed
    // TODO add your handling code here:
    if (file != null) {
        saveFile(file);
    } else {
        this.saveAs();
    }
}//GEN-LAST:event_saveMenuItemActionPerformed

private void setPasswordMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_setPasswordMenuItemActionPerformed
    // TODO add your handling code here:
    setPass();
}//GEN-LAST:event_setPasswordMenuItemActionPerformed

private void saveasMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveasMenuItemActionPerformed
    // TODO add your handling code here:
    saveAs();
}//GEN-LAST:event_saveasMenuItemActionPerformed

    /**
     * Salva un fichero pero pidiendo un nuevo nombre de fichero al usuario
     */
    private void saveAs() {
        JFileChooser chooser = new JFileChooser() {

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }

                for (int i = 0; i < formats.length; i++) {
                    if (file.getPath().endsWith(formats[i])) {
                        return true;
                    }
                }

                return false;
            }
        };

        chooser.setMultiSelectionEnabled(false);

        chooser.setDialogTitle(bundle.getString("chooserSave.text"));

        if (chooser.showSaveDialog(getParent()) == JFileChooser.APPROVE_OPTION) {
            saveFile(chooser.getSelectedFile());
        }
    }

    /**
     * Save file
     */
    private void saveFile(File sel) {
        try {
            byte[] res = null;
            if (sel.getAbsolutePath().toLowerCase().endsWith(FORMAT_TXT)) {
                if (javax.swing.JOptionPane.showConfirmDialog(this, bundle.getString("saveTxtFormat.text"), bundle.getString("saveTxtFormat.tittle"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
                    return;
                }
                res = textArea.getText().getBytes();
            } else {
                if (password == null) {
                    setPass();
                }

                if (password == null) {
                    javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgNoPassSave.text"));
                    return;
                }

                res = SimpleCipherTextClass.recode(textArea.getText().getBytes(), password, Cipher.ENCRYPT_MODE);
            }
            if (writeFile(sel, res)) {
                file = sel;
                this.setTitle(TITLE + " " + SVERSION + ": " + sel.getName());
            }
        } catch (FileNotFoundException e) {
            javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgFileNoFound.text"));
            System.err.println(e);
        } catch (Exception e) {
            javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgUnknownSave.text"));
            System.err.println(e);
        }
    }

    /**
     * Guarda una cadena de texto en un fichero
     * @return Si la operacion se realizo con exito se devuelve true, false en caso contrario
     */
    private static boolean writeFile(File file, byte[] txt) throws FileNotFoundException, IOException {
        FileOutputStream fOut = new FileOutputStream(file);
        fOut.write(txt);
        fOut.close();
        return true;
    }

private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMenuItemActionPerformed
    // TODO add your handling code here:
    JFileChooser chooser = new JFileChooser() {

        @Override
        public boolean accept(File file) {
            if (file.isDirectory()) {
                return true;
            }

            for (int i = 0; i < formats.length; i++) {
                if (file.getPath().endsWith(formats[i])) {
                    return true;
                }
            }

            return false;
        }
    };

    chooser.setMultiSelectionEnabled(false);

    chooser.setDialogTitle(bundle.getString("chooserOpen.text"));

    if (chooser.showOpenDialog(getParent()) == JFileChooser.APPROVE_OPTION) {
        loadFile(chooser.getSelectedFile());
    }
}//GEN-LAST:event_openMenuItemActionPerformed

    /**
     * Carga un fichero de texto en el area de edicion
     */
    private void loadFile(File sel) {
        try {
            String res = "";
            byte[] buff = readFile(sel);
            if (sel.getAbsolutePath().toLowerCase().endsWith(FORMAT_TXT)) {
                res = new String(buff);
            } else {
                if (password == null) {
                    setPass();
                }

                if (password == null) {
                    javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgNoPassOpen.text"));
                    return;
                }

                res = new String(SimpleCipherTextClass.recode(buff, password, Cipher.DECRYPT_MODE));
            }
            textArea.setText(res);

            // Habilita la opcion de guardado simple
            this.saveMenuItem.setEnabled(true);
            // Establece el fichero como el fichero actual, para la opcion de guardar
            file = sel;
            // Establece el titulo de la ventana
            this.setTitle(TITLE + " " + SVERSION + ": " + sel.getName());
        } catch (BadPaddingException e) {
            javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgBadPass.text"));
            System.out.println(e);
            password = null;
        } catch (FileNotFoundException e) {
            javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgFileNoFound.text"));
            System.err.println(e);
        } catch (Exception e) {
            javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgLoad.text"));
            System.out.println(e);
        }
    }

    /**
     * Lee un fichero de texto
     * @return Devuelve el contenido del fichero en una cadena de texto
     */
    public static byte[] readFile(File file) throws FileNotFoundException, IOException {
        byte[] buff = new byte[0];

        buff = new byte[(int) file.length()];
        FileInputStream fIn = new FileInputStream(file);
        fIn.read(buff);
        fIn.close();

        return buff;
    }

    /**
     * Muestra un dialogo para pedir la clave al usuario
     */
    private void setPass() {
        JPasswordField passField = new JPasswordField();
        JPasswordField repPassField = new JPasswordField();

        do {
            switch (javax.swing.JOptionPane.showConfirmDialog(this, new Object[]{bundle.getString("passMsg"), passField, bundle.getString("repPassMsg"), repPassField}, bundle.getString("passMsgTittle"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE)) {
                case (JOptionPane.OK_OPTION):
                    if (!new String(passField.getPassword()).equals(new String(repPassField.getPassword()))) {
                        javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgPassNotEqual.text"));
                        passField.setText("");
                        repPassField.setText("");
                        break;
                    }
                    if (passField.getPassword().length <= 0) {
                        javax.swing.JOptionPane.showMessageDialog(this, bundle.getString("errMsgPassEmpty.text"));
                        passField.setText("");
                        repPassField.setText("");
                        break;
                    }
                    password = new String(passField.getPassword());
                    return;
                case (JOptionPane.CANCEL_OPTION):
                    password = null;
                    return;
            }
        } while (true);
    }

    public static Image scaleImage(Image img, int nX, int nY) {
        ImageIcon imgIcon = new ImageIcon(img);
        float calc1 = (float) nX / imgIcon.getIconWidth();
        float calc2 = (float) nY / imgIcon.getIconHeight();

        calc1 = (calc1 > calc2) ? calc2 : calc1;

        return img.getScaledInstance((int) (calc1 * imgIcon.getIconWidth()), (int) (calc1 * imgIcon.getIconHeight()), java.awt.Image.SCALE_DEFAULT);
    }

    /**
     * Sale del programa
     */
private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
    // TODO add your handling code here:
    System.exit(0);
}//GEN-LAST:event_exitMenuItemActionPerformed
    public static String OPTION_CHAR = "-";

    enum OPTION {

        GUI, G, ENCRYPT, E, DECRYPT, D, PASSWORD, PASS, P, FILEIN, FILE, F, FILEOUT, O, HELP, H
    };

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        boolean gui = (args.length == 0);
        String filein = null;
        String fileout = null;
        int mode = -1;
        String pass = null;
        String arg;

        for (int i = 0; i < args.length; i++) {
            arg = args[i];
            if (arg.startsWith(OPTION_CHAR)) {
                arg = arg.substring(1).toUpperCase();
                OPTION opt = null;
                try {
                    opt = OPTION.valueOf(arg.toUpperCase());
                } catch (IllegalArgumentException e) {
                    exitWithSyntaxMsg(e.toString());
                }

                switch (opt) {
                    case G:
                    case GUI:
                        gui = true;
                        break;
                    case ENCRYPT:
                    case E:
                        if (mode != -1) {
                            exitWithSyntaxMsg("");
                        }
                        mode = Cipher.ENCRYPT_MODE;
                        break;
                    case DECRYPT:
                    case D:
                        if (mode != -1) {
                            exitWithSyntaxMsg("");
                        }
                        mode = Cipher.DECRYPT_MODE;
                        break;
                    case PASSWORD:
                    case PASS:
                    case P:
                        pass = nextArg(args, ++i);
                        break;
                    case FILEIN:
                    case FILE:
                    case F:
                        filein = nextArg(args, ++i);
                        break;
                    case FILEOUT:
                    case O:
                        fileout = nextArg(args, ++i);
                        break;
                    case HELP:
                    case H:
                        System.out.println(bundle.getString("cmdTxtHelpMsg"));
                        ;
                }
            }
        }

        processCmdLine(mode, pass, filein, fileout);

        if (gui || (mode == -1)) {
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    SimpleCipherForm sim = new SimpleCipherForm();
                    sim.setSize(350, 450);
                    sim.setVisible(true);
                }
            });
        }
    }

    private static void processCmdLine(int mode, String pass, String filein, String fileout) {
        if (mode != -1) {
            if (pass == null) {
                exitWithSyntaxMsg(bundle.getString((mode == Cipher.ENCRYPT_MODE) ? "errMsgNoPassSave.text" : "errMsgNoPassOpen.text"));
            }
            byte[] buffIn = null;
            if (filein != null)
            {
            try {
                buffIn = readFile(new File(filein));
            } catch (FileNotFoundException ex) {
                exitWithSyntaxMsg(bundle.getString("errMsgFileNoFound.text"), ex);
            } catch (IOException ex) {
                exitWithSyntaxMsg(bundle.getString("errMsgLoad.text"), ex);
            }}
            else
            {
                String sTmp = "";
                int iTmp;
                try {
                    while ((iTmp = System.in.read()) != -1) {
                        sTmp += (char)iTmp;
                    }
                } catch (IOException ex) {
                    exitWithSyntaxMsg(ex.toString());
                }
                buffIn = sTmp.getBytes();
            }

            byte[] buffOut = null;
            try {
                buffOut = SimpleCipherTextClass.recode(buffIn, pass, mode);
            } catch (Exception e) {
                exitWithSyntaxMsg(e.toString());
            }

            if (fileout != null) {
                try {
                    writeFile(new File(fileout), buffOut);
                } catch (FileNotFoundException ex) {
                    exitWithSyntaxMsg(bundle.getString("errMsgFileNoFound.text"), ex);
                } catch (IOException ex) {
                    exitWithSyntaxMsg(bundle.getString("errMsgSave.text"), ex);
                }
            } else {
                System.out.print(new String(buffOut));
            }
        }
    }

    private static void exitWithSyntaxMsg(String str) {
        exitWithSyntaxMsg(str, null);
    }

    private static void exitWithSyntaxMsg(String str, Exception e) {
        System.err.println("Error: " + str + ((e != null) ? ": " + e : ""));
        System.out.println(bundle.getString("cmdTxtHelpMsg"));
        System.exit(-1);
    }

    private static String nextArg(String[] args, int i) {
        if (args.length < i) {
            System.err.println(args[i - 1]);
            System.out.println(bundle.getString("cmdTxtHelpMsg"));
        }
        return args[i];
    }
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JMenuItem aboutOfMenuItem;
  private javax.swing.JMenuItem exitMenuItem;
  private javax.swing.JMenuBar jMenuBar1;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JSeparator jSeparator1;
  private javax.swing.JSeparator jSeparator3;
  private javax.swing.JSeparator jSeparator4;
  private javax.swing.JSeparator jSeparator5;
  private javax.swing.JMenuItem newMenuItem;
  private javax.swing.JMenuItem openMenuItem;
  private javax.swing.JMenu optMenu;
  private javax.swing.JMenuItem saveMenuItem;
  private javax.swing.JMenuItem saveasMenuItem;
  private javax.swing.JMenuItem setPasswordMenuItem;
  private simpleciphertext.SimpleEditorTextArea textArea;
  // End of variables declaration//GEN-END:variables
}
